/*
 * Copyright 2013-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.tinem.platform.web.gateway.filter;

import cn.hutool.core.util.StrUtil;
import com.google.common.net.HttpHeaders;
import com.tinem.platform.module.pojo.co.GatewayHeadName;
import com.tinem.platform.module.pojo.co.RedisKeyEnum;
import com.tinem.platform.web.gateway.util.GatewayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * GatewayFilter that modifies the respons body.
 */
@Slf4j
@Component
public class CacheParamsGatewayFilterFactory extends
        AbstractGatewayFilterFactory<Object> {

    @Value("${spring.profiles.active}")
    String active;
    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Override
    public GatewayFilter apply(Object config) {
        return (exchange, chain) -> {
            String gatewayRequestId = GatewayUtil.getReq(exchange);

            Map<String,String> req = new Hashtable<>(30,1);

            // --------浏览器信息 ------------
            req.put(HttpHeaders.USER_AGENT, StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst(HttpHeaders.USER_AGENT),""));
            req.put(HttpHeaders.ORIGIN,StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst(HttpHeaders.ORIGIN),""));
            req.put(HttpHeaders.REFERER,StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst(HttpHeaders.REFERER),""));
            req.put(HttpHeaders.HOST,StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst(HttpHeaders.HOST),""));

            // ---------cloudflare ------
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_IP,StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst("Cf-Connecting-Ip"),""));
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_IP_COUNTRY,StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst("Cf-Ipcountry"),""));

            // ---------请求参数缓存 ------
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_TIMESTAMP, String.valueOf(GatewayUtil.getReqTimestamp(exchange)));
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_SERVICE,GatewayUtil.getApiService(exchange));
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_METHOD,GatewayUtil.getApiMethod(exchange));
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_VERSION,StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_VERSION),""));
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_API_REQUEST_ID,GatewayUtil.getApiReq(exchange));
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_JWT,GatewayUtil.getJwt(exchange));
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_CHARSET,StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_CHARSET),""));
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_LANG,StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_LANG),""));

            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_SIGN_TYPE, StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_SIGN_TYPE),""));
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_SIGN, StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_SIGN),""));

            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_CRYPTO_TYPE,StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_CRYPTO_TYPE),""));
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_CRYPTO_KEY,StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_CRYPTO_KEY),""));
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_CRYPTO_IV,StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_CRYPTO_IV),""));

            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_DEBUG,StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_DEBUG),""));
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_DEVICE,StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_DEVICE),""));

            // ---------网关参数缓存 ------
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQUEST_ID,gatewayRequestId);
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_CONTEXT_ACCEPT_TIMESTAMP,String.valueOf(GatewayUtil.getReqAcceptTimestamp(exchange)));
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_CONTEXT_JTI,GatewayUtil.getJit(exchange));
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_CONTEXT_CLIENT_ID,GatewayUtil.getClient(exchange));
            req.put(GatewayHeadName.X_PLATFORM_GATEWAY_CONTEXT_ENV,active);

            String userId = exchange.getAttribute(GatewayHeadName.X_PLATFORM_GATEWAY_CONTEXT_USER_ID);
            if(StrUtil.isNotEmpty(userId)){
                req.put(GatewayHeadName.X_PLATFORM_GATEWAY_CONTEXT_USER_ID,userId);
            }
            // ---------请求内容 ------
            String requestBody = exchange.getAttribute(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_BODY);
            if(StrUtil.isNotBlank(requestBody)){
                req.put(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_BODY,requestBody);
            }

            // ---------将数据保存到redis ------
            String key = RedisKeyEnum.gateway_req_info.getKey(gatewayRequestId);
            stringRedisTemplate.opsForHash().putAll(key,req);
            // ---------设置10分钟后过期 ------
            stringRedisTemplate.expire(key,10, TimeUnit.MINUTES);
            return chain.filter(exchange);
        };
    }
}
